package com.iflytek.jzcpx.procuracy.card.pojo;

import java.io.IOException;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.iflytek.jzcpx.procuracy.card.common.enums.XYRFieldNameEnum;
import com.iflytek.jzcpx.procuracy.card.component.SetList;
import com.iflytek.jzcpx.procuracy.common.util.ListCopyUtil;

import lombok.Data;

/**
 * 要素抽取结果
 *
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2019/8/20 16:13
 */
@Data
public class ElleResultData {

	/** 应答码，0：成功，1：失败 */
	private int rc;
	private String res_version;
	private String version;

	private List<ExtractInfoVec> extractInfoVec;

	@Data
	public static class ExtractInfoVec {

		/** 文本抽取信息 */
		private ExtractInfo extractInfo;

		/** 抽取文书类型 */
		private String type;
	}

	@Data
	public static class ExtractInfo {

		/** 案件名称 */
		private Item caseName;

		/** 侦（调）查机关 */
		private Item investigationOrgan;

		/** 卷宗册数 */
		private Item dossierVolumes;

		/** 移送意见 */
		private Item transferOpinion;

		/** 光盘数量 */
		@JsonProperty("CDNumber")
		private Item CDNumber;

		/** 案情摘要 */
		@JsonProperty("case")
		private Item caseX;

		/** 案情摘要时间 **/
		private Item caseTime;

		/** xx书文号(批准逮捕决定书文号/不批准逮捕决定书文号/起诉书文号/不起诉决定书文号/判决书文号) */
		private Item caseNumber;

		/** 审结日期 */
		private Item concludedDate;

		/** 一审判决日期 */
		private Item judgeDateOfFI;

		/** 认罪认罚适用程序 **/
		private Item applicableProceduresOfGuiltyPlea;

		/** 移送何法院 **/
		private Item courtTransferredTo;

		/** 共同犯罪性质 **/
		private Item natureOfJointCrime;

		/** 是否涉及恶势力犯罪 **/
		private Item viciousPower;

		/** 嫌疑人 */
		private List<Suspect> suspect;

	}

	@Data
	public static class Suspect {

		/** 嫌疑人相关标签归属人 */
		// private Item belonger;

		/** 嫌疑人相关三级标签 */
		private Label label;
	}

	@Data
	public static class CompulsoryMeasureCondition {

		/** 强制措施 */
		private Item compulsoryMeasure;

		/** 强制措施决定日期 */
		private Item compulsoryMeasureDate;

		/** 批准（决定）机关 **/
		private Item approvalAuthority;

		/** 执行机关名称 */
		private Item executiveOrgan;

		/** 执行日期(引擎无反馈字段及结果，可从“强制措施决定日期”字段取值) */
		private Item executiveDate;

		/** 强制措施地点 **/
		private Item compulsoryMeasureAdd;

		/** 保证人姓名 **/
		private Item[] guarantorName;

		/** 保证金（万元） **/
		private Item[] guarantyFund;

		public Item getCompulsoryMeasureDate() {
			if (null == compulsoryMeasureDate) {
				return executiveDate;
			}
			return compulsoryMeasureDate;
		}

		public Item getExecutiveDate() {
			if (null == executiveDate) {
				return compulsoryMeasureDate;
			}
			return executiveDate;
		}
	}

	@Data
	public static class Label {

		/** 姓名 */
		private Item[] suspectName;

		/** 性别 */
		private Item[] gender;

		/** 出生日期 */
		private Item[] birthday;

		/** 证件类型 */
		private Item[] certificates;

		/** 证件号码 */
		private Item[] certificatesId;

		/** 民族 */
		private Item[] ethnicity;

		/** 国籍 */
		private Item[] nationality;

		/** 户籍所在地 */
		private Item[] householdRegisterAddress;

		/** 住所地详细地址 */
		private Item[] detailedAddress;

		/** 工作单位/所在学校 */
		private Item[] workplace;

		/** 单位/学校所在地（省市县（区）一级） */
		/* private Item[] workplaceAddress; */

		/** 受教育状况 */
		private Item[] education;

		/** 政治面貌 */
		private Item[] politicalStatus;

		/** 主要作案地 */
		private Item[] crimePlace;

		/** 住所地 */
		private Item[] address;

		/** 职级 */
		private Item[] rank;

		/** 职务 */
		private Item[] post;

		/** 职业 */
		private Item[] occupation;

		/** 身份 */
		private Item[] identity;

		/** 审结处理结果 */
		private Item[] arrestConcludedResults;

		/** 审结处理结果 */
		private Item[] notArrestConcludedResults;

		/** 审结罪名 */
		private Item[] concludedCharges;

		/** 审结情况 */
		private Item[] concludedSituation;

		/** 审结数额（万元） */
		private Item[] concludedAmount;

		/** 移送法院日期 */
		private Item[] transferDateToCourt;

		/** 检察机关是否适用认罪认罚 */
		private Item[] procuratorateApplyingGuiltyPlea;

		/** 案件造成伤亡情况 */
		private Item[] injuriesAndDeaths;

		/** 是否委托辩护人(引擎无反馈字段及结果) */
		private Item[] advocateByMandate;

		/** 听取辩护人/值班律师意见日期(引擎无反馈字段及结果) */
		private Item[] dateOfHearing;

		/** 公开审查时间(引擎无反馈字段及结果) */
		private Item[] openCensorshipTime;

		/** 提起公诉日期(引擎无反馈字段及结果，可从“移送法院日期”字段取值) */
		private Item[] prosecutionDate;

		/** 审结处理情况(引擎无反馈字段及结果，可从“审结情况”字段取值) */
		private Item[] concludedProcessingSituation;

		/** 审查认定的法定情节(引擎无反馈字段及结果) */
		private Item[] legalPlotOfReview;

		/** 一审判决罪名 */
		private Item[] chargeOfFI;

		/** 一审宣告刑（主刑） */
		private Item[] principalPenaltyOfFI;

		/** 一审宣告刑刑期 */
		private Item[] prisonTermOfFI;

		/** 一审缓刑考验期 */
		private Item[] probationTermOfFI;

		/** 一审附加刑类型 */
		private Item[] accessoryPenaltyOfFI;

		/** 一审附加刑具体情况 */
		private Item[] accessoryPenaltyContentOfFI;

		/** 一审罚金数额（万元） */
		private Item[] fineOfFI;

		/** 裁判认定法定情节(引擎无反馈字段及结果) */
		private Item[] legalPlotOfJudgment;

		/** 强制措施 **/
		private List<CompulsoryMeasureCondition> compulsoryMeasureCondition;

		// R版本后处理引擎新增字段信息
		private Item[] nameUsedBefore; // 曾用名
		private Item[] nickName; // 绰号
		private Item[] npcMember; // 人大代表
		private Item[] cppccMember; // 政协委员
		private Item[] ruralGrassroofsOrgPersonnel; // 是否农村基层组织人员
		private Item[] time; // 作案时间
		private Item[] otherIdentity; // 其他关注身份（*）
		private Item[] criminalRecord; // 刑事处罚（*）
		private Item[] indoctrinationLabour; // 劳教（*）
		private Item[] orgName; // 单位名称（*）
		private Item[] orgNature; // 单位性质（*）
		private Item[] orgAddress; // 单位所在地址（*）
		private Item[] orgCode; // 组织机构代码（*）
		private Item[] legalRepseName; // 法定代表人姓名（*）
		private Item[] legalRepsepost; // 法定代表人职务（*）
		private Item[] litigantRepreseName; // 诉讼代表人姓名（*）
		private Item[] litigantRepresePost; // 诉讼代表人职务（*）
		private Item[] litigantRepreseTel; // 诉讼代表人联系方式（*）
		private Item[] litigationCharges; // 移诉案由(原“移诉罪名”)
		private Item[] investigationApplyingGuiltyPlea; /// 侦查机关是否建议适用认罪认罚
		private Item[] nativePlace;// 籍贯
		private Item[] workplaceArea;// 工作单位/学校所在地
		
		//住所地详细地址
		public Item[] getDetailedAddress() {
			if (ArrayUtils.isEmpty(detailedAddress) && ArrayUtils.isNotEmpty(address)) {
				List<Item> addressList = Arrays.asList(address);
				List<Item> addressListCopy = null;
				try {
					addressListCopy = ListCopyUtil.deepCopy(addressList);
				} catch (ClassNotFoundException | IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				addressListCopy.forEach(v -> v.setMean(v.getOrg_text()));
				Item[] addressItem = addressListCopy.toArray(new Item[addressListCopy.size()]);
				return addressItem;
			}
			return detailedAddress;
		}
		
		// 审结时强制措施状态
		public Item[] getSJSQZCSZT() {
			Item[] sJSQZCSZTItemArray = new Item[1];
			if (CollectionUtils.isEmpty(compulsoryMeasureCondition)) {
				Item sJSQZCSZTItem = new Item();
				sJSQZCSZTItem.setMean("无强制措施");
				sJSQZCSZTItemArray[0] = sJSQZCSZTItem;
				return sJSQZCSZTItemArray;
			}
			// 强制措施排序
			List<Item> compulsoryMeasureList = compulsoryMeasureCondition.stream().map(v -> v.getCompulsoryMeasure())
					.collect(Collectors.toList());
			compulsoryMeasureList.sort(Comparator.comparing(Item::getPos_begin));
			// 取最后一条强制措施
			Item lastCompulsoryMeasureConditionItem = compulsoryMeasureList.get(compulsoryMeasureList.size() - 1);
			sJSQZCSZTItemArray[0] = lastCompulsoryMeasureConditionItem;
			return sJSQZCSZTItemArray;
		}

		// 审结处理结果
		public Item[] getArrestConcludedResults() {
			if (ArrayUtils.isEmpty(arrestConcludedResults)) {
				arrestConcludedResults = notArrestConcludedResults;
			}
			return arrestConcludedResults;
		}

		// 出生日期抽取为空 则从身份证件中取
		public Item[] getBirthday() {
			String[] parsePatterns = { "yyyy-MM-dd" };
			if (ArrayUtils.isNotEmpty(birthday)) {
				List<Item> items = Arrays.asList(birthday);
				// 出身日期符合yyyy-mm-dd格式的筛选出来
				items = items.stream().filter(v -> {
					try {
						return null != DateUtils.parseDate(v.getMean(), parsePatterns);
					} catch (ParseException e) {
						return false;
					}
				}).collect(Collectors.toList());
				birthday = items.toArray(new Item[items.size()]);
			}
			if (ArrayUtils.isEmpty(birthday) && ArrayUtils.isNotEmpty(certificatesId)) {
				List<Item> items = Arrays.asList(certificatesId);
				items = items.stream().filter(v -> StringUtils.isNotEmpty(v.getMean()))
						.filter(v -> (v.getMean().length() == 15 || v.getMean().length() == 18))
						.collect(Collectors.toList());
				if (CollectionUtils.isNotEmpty(items)) {
					List<Item> csrqItemList = items.stream().map(v -> install(v)).collect(Collectors.toList());
					birthday = csrqItemList.toArray(new Item[csrqItemList.size()]);
					return birthday;
				}
			}
			return birthday;
		}

		private Item install(Item item) {
			String mean = item.getMean().substring(6, 10) + "-" + item.getMean().substring(10, 12) + "-"
					+ item.getMean().substring(12, 14);
			Item csrqItem = new Item();
			csrqItem.setMean(mean);
			csrqItem.setPos_begin(item.getPos_begin() + 6);
			csrqItem.setPos_end(item.getPos_begin() + 13);
			csrqItem.setOrg_text(mean);
			return csrqItem;
		}
		// 职业、身份互补
		/*
		 * public Item[] getIdentity() { if(ArrayUtils.isEmpty(identity)) { return
		 * occupation; } return identity; }
		 * 
		 * public Item[] getOccupation() { if(ArrayUtils.isEmpty(occupation)) { return
		 * identity; } return occupation; }
		 */

		// 户籍所在地为空则取 籍贯标签
		public Item[] getHouseholdRegisterAddress() {
			if (ArrayUtils.isEmpty(householdRegisterAddress)) {
				return nativePlace;
			}
			return householdRegisterAddress;
		}

		// 姓名 存在大写变小写情况 取原始值
		public Item[] getSuspectName() {
			if (ArrayUtils.isNotEmpty(suspectName)) {
				List<Item> itemList = Arrays.asList(suspectName);
				itemList.forEach(p -> p.setMean(p.getOrg_text()));
				suspectName = itemList.toArray(new Item[itemList.size()]);
				return suspectName;
			}
			return null;
		}

		// 证件号码 存在大写变小写情况 取原始值
		public Item[] getCertificatesId() {
			if (ArrayUtils.isNotEmpty(certificatesId)) {
				List<Item> itemList = Arrays.asList(certificatesId);
				itemList.forEach(p -> p.setMean(p.getOrg_text()));
				certificatesId = itemList.toArray(new Item[itemList.size()]);
				return certificatesId;
			}
			return null;
		}

		// 前科
		public Item[] getQk() {
			if (ArrayUtils.isNotEmpty(criminalRecord)) {
				List<Item> items = Arrays.asList(criminalRecord);
				items.forEach(p -> p.setMean(XYRFieldNameEnum.XSCF.getMc()));
				criminalRecord = items.toArray(new Item[items.size()]);
				ElleResultData.Item[] temp = new ElleResultData.Item[1];
				System.arraycopy(criminalRecord, 0, temp, 0, 1);
				return temp;
			} else if (ArrayUtils.isEmpty(criminalRecord) && ArrayUtils.isNotEmpty(indoctrinationLabour)) {
				List<Item> items = Arrays.asList(indoctrinationLabour);
				items.forEach(p -> p.setMean(XYRFieldNameEnum.LJ.getMc()));
				indoctrinationLabour = items.toArray(new Item[items.size()]);
				ElleResultData.Item[] temp = new ElleResultData.Item[1];
				System.arraycopy(indoctrinationLabour, 0, temp, 0, 1);
				return temp;
			} else {
				Item qkItem[] = new Item[1];
				Item item = new Item();
				item.setMean("无");
				qkItem[0] = item;
				return qkItem;
			}
		}

		// 审结罪名(取审结案由中第一个作为审结罪名)
		public Item[] getConcludedCharges() {
			if (ArrayUtils.isNotEmpty(concludedCharges)) {
				ElleResultData.Item[] temp = new ElleResultData.Item[1];
				System.arraycopy(concludedCharges, 0, temp, 0, 1);
				return temp;
			}
			return null;
		}

		// 审结其他罪名(引擎无反馈字段及结果，可从“审结罪名”字段取值)
		public Item[] getOtherConcludedCharges() {
			if (ArrayUtils.isNotEmpty(concludedCharges) && concludedCharges.length > 1) {

				String firstMean = concludedCharges[0].getMean();
				SetList<String> setList = new SetList<String>();
				List<ElleResultData.Item> itemList = new ArrayList<ElleResultData.Item>();
				ElleResultData.Item[] temp = new ElleResultData.Item[concludedCharges.length - 1];
				System.arraycopy(concludedCharges, 1, temp, 0, temp.length);
				if (ArrayUtils.isEmpty(temp)) {
					return null;
				}
				for (ElleResultData.Item item : temp) {
					String mean = item.getMean();
					if (StringUtils.isNotBlank(mean) && !setList.contains(mean) && !firstMean.equals(mean)) {
						itemList.add(item);
						setList.add(mean);
					}
				}
				if (CollectionUtils.isNotEmpty(itemList)) {
					ElleResultData.Item[] items = itemList.toArray(new ElleResultData.Item[itemList.size()]);
					return items;
				}

			}
			return null;
		}

		// 一审判决罪名 :引擎返回数组，应用解析第一个是主要罪名，其余的是其他罪名
		public Item[] getChargeOfFI() {
			if (ArrayUtils.isNotEmpty(chargeOfFI)) {
				List<Item> itemList = Arrays.asList(chargeOfFI);
				// 罪名按照mean去重
				ArrayList<Item> distinctByMean = itemList.stream()
						.collect(Collectors.collectingAndThen(
								Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Item::getMean))),
								userOrders -> new ArrayList<>(userOrders)));
				chargeOfFI = distinctByMean.toArray(new Item[distinctByMean.size()]);
				ElleResultData.Item[] temp = new ElleResultData.Item[1];
				System.arraycopy(chargeOfFI, 0, temp, 0, 1);
				return temp;
			}
			return null;
		}

		// 一审判决其他罪名:引擎返回数组，应用解析第一个是主要罪名，其余的是其他罪名
		public Item[] getOtherChargeOfFI() {
			if (ArrayUtils.isNotEmpty(chargeOfFI) && chargeOfFI.length > 1) {
				ElleResultData.Item[] temp = new ElleResultData.Item[chargeOfFI.length - 1];
				System.arraycopy(chargeOfFI, 1, temp, 0, temp.length);
				return temp;
			}
			return null;
		}

		/** 移送案由 **/
		public Item[] getLitigationCharges() {
			if (ArrayUtils.isNotEmpty(litigationCharges)) {
				ElleResultData.Item[] temp = new ElleResultData.Item[1];
				System.arraycopy(litigationCharges, 0, temp, 0, 1);
				return temp;
			}
			return null;
		}

		/** 移送其他案由 **/
		public Item[] getOtherLitigationCharges() {
			if (ArrayUtils.isNotEmpty(litigationCharges) && litigationCharges.length > 1) {
				String firstMean = litigationCharges[0].getMean();
				SetList<String> setList = new SetList<String>();
				List<ElleResultData.Item> itemList = new ArrayList<ElleResultData.Item>();
				ElleResultData.Item[] temp = new ElleResultData.Item[litigationCharges.length - 1];
				System.arraycopy(litigationCharges, 1, temp, 0, temp.length);
				if (ArrayUtils.isEmpty(temp)) {
					return null;
				}
				for (ElleResultData.Item item : temp) {
					String mean = item.getMean();
					if (StringUtils.isNotBlank(mean) && !setList.contains(mean) && !firstMean.equals(mean)) {
						itemList.add(item);
						setList.add(mean);
					}
				}
				if (CollectionUtils.isNotEmpty(itemList)) {
					ElleResultData.Item[] items = itemList.toArray(new ElleResultData.Item[itemList.size()]);
					return items;
				}
			}
			return null;
		}

		// 提起公诉日期(引擎无反馈字段及结果，可从“移送法院日期”字段取值)
		public Item[] getProsecutionDate() {
			return transferDateToCourt;
		}

		// 审结处理情况(引擎无反馈字段及结果，可从“审结情况”字段取值)
		public Item[] getConcludedProcessingSituation() {
			return concludedSituation;
		}

	}

	@Data
	public static class Item implements Serializable{

		/**
		 * 
		 */
		private static final long serialVersionUID = 7810207573962500400L;
		/** 规整过的语义信息，不带换行符 */
		private String mean;
		/** 原文对应片段 */
		private String org_text;
		/** 原文片段起始位置， 从文章开始算起 */
		private int pos_begin;
		/** 原文片段结束位置， 从文章开始算起 */
		private int pos_end;
	}

}
